# The "main" function...
# will want to wrap up the little code turds into classes/fns in a bit

# modules installed in system
##################################################
# does importing modules everywhere use extra memory?
import cv # opencv bindings; installed in package manager
import sys # system specific crap, LIKE sys.argv etc.
import os # system interfaces
import string
import numpy
#import Image
##################################################

##################################################
# modules from this project
from HelperFunctions import *
from WormCountConfigs import *
from ImageJFormat import *
# this depends on Configs
from ChunkImages import *
#this depends on OpenCV and lotsa other crap like that
#from CVGui import *
from CVGuiClasses import *
##################################################

##################################################
if __name__ == '__main__':

  ####### configuration
  # this will be majorly refactored
  configs=Configs() #jesus fuck this feels sloppy
  interactive = True # interactively flag objects?
  chunking = True # chunk images?

  ####### GUI init
  worm = GuiWindow('wormage')
  plate = GuiWindow('the big picture')
  wind1 = 'wormage'
  wind2 = 'the big picture'
  framebuffer_big = cv.CreateMat(configs.bigframerows,configs.bigframecols,0) # should be rgb colorspace maybe

  ####### I/O init

  ####### variables
  key = -1 #the keyboard
  nworms = -1 #number of worms
  #worms = {} # will probs be a dict (?) of Worm-s
  label = '' # photo filename without extension
  datafile = None # this will be the obkects file from imagej
  objects = None # numpy (lol) array of this file
  cropped = None # this is the cropped region
  thisimage = None # plate photo; CvMat type
  #here = os.getcwd() #dunno maybe there's a better keyword

  # this is perfectly legible
  files = list(set([ x.split('-')[0] for x in os.listdir(os.getcwd())]))
  print 'loading plate pics: '+str(files) #bite down, killer-- here comes the fun!
  
  ##################################
  ####### loops; poops
  for platephoto in files: #for all plate photos
    #MkDir(os.path.join(configs.here+configs.outputpath+label+configs.sortedpath))
    # really, configs should make these all and the paths should be absolute
    # OR the paths should just be hardcoded you fucking jackass
    outputpath = os.path.join(os.getcwd(),platephoto+'-analysis')
    MkDir(outputpath)
    countsfile = open(os.path.join(outputpath,'counts-'+platephoto+'.tsv'),'w')
    
    #thisimage = cv.LoadImageM(os.path.join(os.getcwd(),platephoto+'-crop-bkg.png'),iscolor=2)
    thisimage = cv.LoadImageM(os.path.join(os.getcwd(),platephoto+'-crop.png'),iscolor=2)
    
    #label = platephoto.split('.')[0] # filename of photo without the extension
    # will want to make this more flexible..
    datafile = open(os.path.join(os.getcwd(),platephoto+'-particles.txt')) # work plz

    objects = numpy.genfromtxt(datafile,skiprows=1)
    #datafile.close() # don't need this after it's copied
    objectspath = os.path.join(outputpath,'objects/')
    MkDir(objectspath)

    for index in range(len(objects[:,1])):
      chunk = index
      #### for each chunk
      thisobject = objects[index,:]
      bounding_rect = tuple(thisobject[6:10])
      # maybe the rectangle should be extended by a 1px boundary,
      # to avoid edge efx. but that's a pain.
      bounding_rect = tuple(map(lambda x:int(x),bounding_rect))
      print bounding_rect
      cropped = cv.GetSubRect(thisimage, bounding_rect)
      # jesus fucking christ 
      cv.SaveImage(os.path.join(objectspath,str(index)+'.png'), cropped)
      #################################
      #### GUI CRAP GOES HERE

      # in non-chunk mode, the line below replaces index in objects # idk 'chunk mode'
      #for chunk in os.listdir(configs.here+configs.outputpath+configs.objectprefix+label):
      # umm i don't know why 'cropped' isn't copied but it works so fuck-it... refactor in the future # maybe it's some color space shit
      loadme = cv.LoadImageM(os.path.join(objectspath,str(index)+'.png'),iscolor=2)
      #loadme = cropped # fails because a subrect is just apointer to the big image
      iaverage = cv.AvgSdv(loadme)[0][0]
      istdev = cv.AvgSdv(loadme)[1][0]
      #print iaverage
      #print istdev
      cv.ConvertScale(loadme,loadme,1,-iaverage)
      #cv.AdaptiveThreshold(loadme,loadme,200)
      #cv.EqualizeHist(loadme,loadme)
      #cv.Pow(loadme,loadme,2)
      #THISWORKS.
      aspect = (float(loadme.cols)/float(loadme.rows))
      #print aspect
      framebuffer = cv.CreateMat(int(configs.framerows),int(aspect*configs.framerows),0)
      #cv.AdaptiveThreshold(loadme,loadme,200)
      #cv.EqualizeHist(loadme,loadme)
      cv.Resize(loadme,framebuffer,interpolation=0)
      #cv.EqualizeHist(framebuffer,framebuffer)
      # cvmat has cvmat.rows, .cols
      #0: nearest neighbor
      #1: bilinear??
      #cv.AdaptiveThreshold(framebuffer,framebuffer,127)
      # as (min max (minloc xminval = cv.MinMaxLoc(framebuffer)[0]
      minval = cv.MinMaxLoc(framebuffer)[0]
      maxval = cv.MinMaxLoc(framebuffer)[1]
      print minval,maxval
      #cv.EqualizeHist(framebuffer,framebuffer)
      # BEST SO FAR
      
      # CHANGED
      cv.ConvertScale(framebuffer,framebuffer,scale=(maxval-minval),shift=-1*minval)
      #cv.Scale(framebuffer,framebuffer,maxval-minval)
      #cv.Scale(framebuffer,framebuffer,100)
      
      #cv.Pow(framebuffer,framebuffer,2) #ACTUALLY, gamma is ^(1/gamma)
      # PYTHON'S WHITE SPACE SYNTAX SUCKS BECAUSE VERY FEW EDITORS CAN INDENT BLOCKS OF TEXT EASILY.
      cv.ShowImage(wind1,framebuffer)
      ############################
      # bigpicture stufjf
      ############################
      #thisimage = cv.LoadImageM(configs.here+platephoto,iscolor=2)
      #cropped = cv.GetSubRect(thisimage, bounding_rect) # tuple: (x,y,dx,dy)
      #cv.Resize(loadme,framebuffer,interpolation=0)

      # oh wait... it's NOT a copy!!! modifying the subrect modifies the original!!!
      # ALSO, does this mean a subrect can't be ShowImage'd directly?
      #croppedimage = cv.GetSubRect(thisimage, bounding_rect) # tuple: (x,y,dx,dy)
      #cv.Rectangle(croppedimage,(100,100),(200,200),cv.RGB(255,0,0),thickness=3)
      print bounding_rect
      corner1 = (bounding_rect[0]-1, bounding_rect[1]-1)
      corner2 = (bounding_rect[0]+bounding_rect[2]+1, bounding_rect[1]+bounding_rect[3]+1)
      cv.Rectangle(thisimage,corner1,corner2,cv.RGB(127,127,127),thickness=1)
      #Rectangle(img, pt1, pt2, color, thickness=1, lineType=8, shift=0)
      # the bounding rect with a naighborhood around it; or clipped to the image edge. should be its own function, possibly as member of gui window class.
      
      # this otter be in a class or summat
      framed_br = (max(bounding_rect[0]-7,0),max(bounding_rect[1]-7,0),max(bounding_rect[2]+14,0),max(bounding_rect[3]+14,0))
      print framed_br
      
      #cv.Resize(thisimage,framebuffer_big)
      cv.Resize(cv.GetSubRect(thisimage,framed_br),framebuffer_big,interpolation=0)
      
      #original = cv.LoadImageM("building.jpg")
      #thumbnail = cv.CreateMat(original.rows / 10, original.cols / 10, cv.CV_8UC3)
      #cv.Resize(original, thumbnail)
      
      #key = cv.WaitKey(delay=-1)
      
      #cv.ConvertScale(framebuffer_big,framebuffer_big,25,1)
      minval_big = cv.MinMaxLoc(framebuffer_big)[0]
      maxval_big = cv.MinMaxLoc(framebuffer_big)[1]
      cv.ConvertScale(framebuffer_big,framebuffer_big,scale=1,shift=-10)
      #cv.EqualizeHist(framebuffer_big,framebuffer_big)
      
      cv.ShowImage(wind2,framebuffer_big)
      #the corner can only be strictly greater than, so just limit to image width - lesser corner

      ############################
      # wait for input
      ############################
      key = cv.WaitKey(delay=-1)
      #print chunk
      #48 to 57 = 0 to 9
      #print key - 48
      # TODO VERIFY THE NUMBERS WORK
      # TODO BETTER KEYBOARD INPUT
      if key == 13: break #graceful exit? NO
      nworms = key-48 # need a better converter
      print str(chunk)+': '+str(nworms)+' worms'

      countsfile.write(str(chunk)+'\t'+str(nworms)+'\n')
      # idk what this is doing here
      # oh wait, it's re-loading (*cringe*) the image because there's now a rectangle scrawled over it
      #thisimage = cv.LoadImageM(os.path.join(os.getcwd(),platephoto+'-crop.png'),iscolor=2)
      #thisimage = cv.LoadImageM(os.path.join(os.getcwd(),platephoto+'-crop-bkg.png'),iscolor=2)
      thisimage = cv.LoadImageM(os.path.join(os.getcwd(),platephoto+'-crop.png'),iscolor=2)
      #########################################################
      # loop ends
      #########################################################
    #should prolly flush as it's written?
    datafile.close()

##################################################
####### cleanup
  countsfile.close()
##################################################